package com.tangyuan.video.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangyuan.common.result.Result;
import com.tangyuan.common.result.ResultCodeEnum;
import com.tangyuan.common.util.VideoOSSUtils;
import com.tangyuan.dto.VideoPublisherDto;
import com.tangyuan.feignapis.user.IUserActionFeignClient;
import com.tangyuan.feignapis.user.IUserFeignClient;
import com.tangyuan.model.UserAction;
import com.tangyuan.model.Video;
import com.tangyuan.video.mapper.*;
import com.tangyuan.video.service.VideoCollectionService;
import com.tangyuan.video.service.VideoService;
import com.tangyuan.video.service.VideoThumpService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class VideoServiceImpl extends ServiceImpl<VideoMapper, Video> implements VideoService {
    @Autowired
    VideoMapper videoMapper;
    @Autowired
    private VideoCommentMapper  videoCommentMapper;
    @Autowired
    private VideoHotMapper videoHotMapper;
    @Autowired
    private VideoThumpMapper videoThumpMapper;
    @Autowired
    private VideoThumpService videoThumpService;
    @Autowired
    private VideoCollectionService videoCollectionService;
    @Autowired
    private IUserFeignClient userFeignClient;
    @Autowired
    private IUserActionFeignClient userActionFeignClient;

    @Override
    public Result<ResultCodeEnum> deleteById(Long videoId, Long userId) {
        if (videoId == null || userId == null) {
            return Result.build(null, ResultCodeEnum.ARGUMENT_VALID_ERROR);
        }
        Video video = videoMapper.selectById(videoId);
        if (video == null) {
            return Result.build(null, ResultCodeEnum.NO_DATA);
        }
        if (!userId.equals(video.getUserId())) {
            return Result.build(null, ResultCodeEnum.YOU_HAVE_NO_CHANGE);
        }
        if (video.getContent()!=null){
            VideoOSSUtils.delOssFile(video.getContent());
        }
        deleteVideoRelatedByVideoId(videoId);
        int result = videoMapper.deleteById(videoId);
        if (result > 0) {
            return Result.ok();
        }
        return Result.build(null, ResultCodeEnum.FAIL);
    }

    private void deleteVideoRelatedByVideoId(Long videoId) {
        userFeignClient.deleteUserActionByVideoId(videoId);
        userFeignClient.deleteUserVideoCollectionByVideoId(videoId);
        videoCommentMapper.deleteByVideoId(videoId);
        videoHotMapper.deleteByVideoId(videoId);
        videoThumpMapper.deleteByVideoId(videoId);
    }

    @Override
    public Video getVideoById(Long videoId, Long userId) {
        if(videoId == null || videoId <= 0){
            return null;
        }
        return videoMapper.getVideoById(videoId, userId);
    }

    @Override
    public List<Video> getVideoByIds(List<Long> videoIds, Long userId) {
        if(CollectionUtils.isEmpty(videoIds)){
            return new ArrayList<>();
        }
        return baseMapper.getVideoByIds(videoIds,userId);
    }

    @Override
    public Result topMyVideo(Long videoId, Long userId) {
        if (videoId == null && userId == null) {
            return Result.build(null, ResultCodeEnum.ARGUMENT_VALID_ERROR);
        }
        Video video = videoMapper.selectById(videoId);
        if (video == null) {
            return Result.build(null, ResultCodeEnum.NO_DATA);
        }
        if (!userId.equals(video.getUserId())) {
            return Result.build(null, ResultCodeEnum.YOU_HAVE_NO_CHANGE);
        }
        if (video.getTop() == 1) {
            toggleVideoTopStatus(video);
            videoMapper.updateById(video);
            return Result.ok();
        } else {
            long topCount = videoMapper.countTopVideosByUserId(userId);
            if (topCount >= 3) {
                return Result.build(null, ResultCodeEnum.BEYOND_TOP_QUANTITY);
            }
            toggleVideoTopStatus(video);
            videoMapper.updateById(video);
            return Result.ok();
        }
    }

    private void toggleVideoTopStatus(Video video) {
        video.setTop(1 - video.getTop());
        video.setTopTime(new Date());
    }

    @Override
    public List<Video> getVideoInfo(Long userId,String name, Integer pageNum, Integer pageSize) {
        QueryWrapper<Video> wrapper = new QueryWrapper<>();
        wrapper.lambda().like(Video::getTitle,name);
        wrapper.lambda().orderByDesc(Video::getCreateTime);
        List<Video> videos = baseMapper.selectPage(new Page<>(pageNum, pageSize), wrapper).getRecords();
        List<Long> ids = videos.stream().map(Video::getId).collect(Collectors.toList());
        return this.getVideoByIds(ids,userId);
    }

    @Override
    public List<Video> getMyVideoByUserId(Long myUserId,Long userId, Integer pageNum, Integer pageSize) {
        QueryWrapper<Video> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Video::getUserId,userId);
        wrapper.lambda().orderByDesc(Video::getTop);
        wrapper.lambda().orderByDesc(Video::getTopTime);
        wrapper.lambda().orderByDesc(Video::getCreateTime);
        IPage<Video> videoIPage = this.page(new Page<>(pageNum, pageSize), wrapper);
        List<Video> videoIds = videoIPage.getRecords();
        List<Long> ids = videoIds.stream().map(Video::getId).collect(Collectors.toList());

        if(CollectionUtils.isEmpty(ids)){
            return new ArrayList<>();
        }

        List<Video> videos=baseMapper.getPublishVideoByIds(ids,myUserId);

        //根据 ids排序
        List<Video> videoList = new ArrayList<>();
        Map<Long, Video> collect = videos.stream().collect(Collectors.toMap(Video::getId, video -> video));
        for (Long headlines : ids) {
            if(collect.containsKey(headlines)){
                videoList.add(collect.get(headlines));
            }
        }

        return videoList;
    }



    @Override
    public Long getVideoThumpNum(Long userId) {
        return videoMapper.getVideoThumpNum(userId);
    }

    @Override
    public List<Video> getMyTrumpVideo(Long userId, Integer pageNum, Integer pageSize) {
        List<Long> thumpIds = videoThumpService.getVideoIdByUserId(userId,pageNum,pageSize);
        return sortVideoByIds(thumpIds,userId);
    }

    @Override
    public List<Video> getMyCollectVideo(Long userId, Integer pageNum, Integer pageSize) {
        List<Long> collectionIds = videoCollectionService.getVideoIdByUserId(userId,pageNum,pageSize);
        return sortVideoByIds(collectionIds,userId);
    }
    @Override
    public Page<Video> getMyActionVideo(Long userId, Integer pageNum, Integer pageSize) {
        Page<UserAction> userActionPage = userActionFeignClient.getPageUserActionByUserId(userId, pageNum, pageSize);
        if(CollectionUtils.isEmpty(userActionPage.getRecords())){
            return new Page<>();
        }
        List<Long> ids = userActionPage.getRecords().stream().map(UserAction::getMovieId).collect(Collectors.toList());
        List<Video> videos = sortVideoByIds(ids, userId);
        Page<Video> page = new Page<>();
        page.setRecords(videos);
        page.setTotal(userActionPage.getTotal());
        return page;
    }

    @Override
    public void updateUserVideoMessage(VideoPublisherDto dto) {
        if(dto == null ||
                (dto.getUserId() == null || dto.getUserId() == 0) ||
                (StringUtils.isEmpty(dto.getNickName()) && StringUtils.isEmpty(dto.getUrl()))){
            log.error("百家修改参数不可为空");
            return;
        }
        videoMapper.update(null,new LambdaUpdateWrapper<Video>()
                .eq(Video::getUserId,dto.getUserId())
                .set(!StringUtils.isEmpty(dto.getUrl()),Video::getPublisherIcon,dto.getUrl())
                .set(!StringUtils.isEmpty(dto.getNickName()),Video::getPublisher,dto.getNickName())
        );
    }



    /**
     * 根据VideoId获取 正确的点赞数评论数的Video数据 并按照参数ids排序
     * @param ids videoIds
     * @param userId 用户
     * @return List<Video>
     */
    private List<Video> sortVideoByIds(List<Long> ids,Long userId){
        if(CollectionUtils.isEmpty(ids)){
            return new ArrayList<>();
        }
        List<Video> videos = this.getVideoByIds(ids, userId);
        //根据 ids排序
        List<Video> videoList = new ArrayList<>();
        Map<Long, Video> collect = videos.stream().collect(Collectors.toMap(Video::getId, video -> video));
        for (Long headlines : ids) {
            if(collect.containsKey(headlines)){
                videoList.add(collect.get(headlines));
            }
        }
        return videoList;
    }

}